package com.kcht.itsed.mws.subscribescheduler.comm;

import com.kcht.itsed.mws.subscribescheduler.biz.IConcreteReportSender;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * HTTP方式发送报告
 * 只包含HTTP发送，不含断链缓存
 * 断链缓存需要使用装饰器
 * 
 * @author zhangwenshuo
 *
 */
@Slf4j
public class HttpReportSender implements IConcreteReportSender {

	protected URI url; 
	
	protected Throwable error;	//是否正在顺利发送
	
	/*
	 * 
	 * URL格式为标准的HTTPurl，例如http://127.0.0.1:999/asdf/qwer/dd.do
	 * 可选的查询字串
	 * 
	 * compress=gzip:GZIP压缩
	 * timeout=2000:超时时间，默认超时时间为2秒，即两秒收不到200 OK则认为发送失败
	 * 
	 */
	
	private Map<String,String> queryMap;
	
	private int timeoutInMs = 2000;	//每次通信延时。默认是2秒
	private boolean gziped = false;	//是否GZIP压缩了
	
	
	public HttpReportSender(URI url,Map<String,String> queryMap) {
		this.url = url;
		this.queryMap = queryMap;
		if(queryMap.containsKey("timeout"))timeoutInMs = Integer.parseInt(queryMap.get("timeout"));
		if(queryMap.containsKey("compress") && queryMap.get("compress").equals("gzip"))gziped = true;
	}

	
	private String isToStr(InputStream is) {
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));   
        StringBuilder sb = new StringBuilder();   
        String line = null;   
        try {   
            while ((line = reader.readLine()) != null) {   
                sb.append(line);   //XML脚本，发送时无需回车
            }   

        } catch (IOException e) {   
            log.error("",e);
        } finally {   
            try {   
                is.close();   
            } catch (IOException e) {   
                log.error("",e);
            }   
        }   

        return sb.toString(); 
	}



	//设置响应超时，连接超时
	private  RequestConfig config=RequestConfig.custom().setSocketTimeout(timeoutInMs).setConnectTimeout(timeoutInMs).build();
	@Override
	public void send(InputStream reportIS)throws ReportSendFailException {
		try(CloseableHttpClient client = HttpClientBuilder
				.create()
				.build()){
			HttpPost post=new HttpPost();
			post.setConfig(config);
			post.setURI(url);
			post.setEntity(new StringEntity(isToStr(reportIS),"utf-8"));
			if(gziped){
				post.addHeader("Content-encoding","gzip");
			}
			try(CloseableHttpResponse response = client.execute(post)){
				int statusCode = response.getStatusLine().getStatusCode();
				if(statusCode>199&&statusCode<300) {
					error = null;
				}else {
					error = new ReportSendFailException("Report receiver["+url+"] response:"+statusCode);
					throw (ReportSendFailException)error;
				}
			}
		} catch (IOException e) {
			error=e.getCause();
			log.error("发送失败，请确保订阅者可达");
			throw new ReportSendFailException(e);
		}
	}

	@Override
	public ReportSendingState getSendingState() {
		if(error == null)return ReportSendingState.SENDING;
		if(error instanceof ReportSendFailException) {
			return ReportSendingState.ERROR;
		}else
			return ReportSendingState.DISCONNECTED;
	}
}
